// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// A subtest of the larger MapTest. Will eliminate once the full
// test is running.

import "package:expect/expect.dart";

class MapTest {
  static void testDeletedElement(Map map) {
    map.clear();
    for (int i = 0; i < 100; i++) {
      map[1] = 2;
      Expect.equals(1, map.length);
      int x = map.remove(1);
      Expect.equals(2, x);
      Expect.equals(0, map.length);
    }
    Expect.equals(0, map.length);
    for (int i = 0; i < 100; i++) {
      map[i] = 2;
      Expect.equals(1, map.length);
      int? x = map.remove(105);
      Expect.equals(null, x);
      Expect.equals(1, map.length);
      x = map.remove(i);
      Expect.equals(2, x);
      Expect.equals(0, map.length);
    }
    Expect.equals(0, map.length);
    map.remove(105);
  }

  static void test(Map map) {
    testDeletedElement(map);
    testMap(map, 1, 2, 3, 4, 5, 6, 7, 8);
    map.clear();
    testMap(map, "value1", "value2", "value3", "value4", "value5", "value6",
        "value7", "value8");
  }

  static void testMap(Map map, key1, key2, key3, key4, key5, key6, key7, key8) {
    int value1 = 10;
    int value2 = 20;
    int value3 = 30;
    int value4 = 40;
    int value5 = 50;
    int value6 = 60;
    int value7 = 70;
    int value8 = 80;

    Expect.equals(0, map.length);

    map[key1] = value1;
    Expect.equals(value1, map[key1]);
    map[key1] = value2;
    Expect.equals(false, map.containsKey(key2));
    Expect.equals(1, map.length);

    map[key1] = value1;
    Expect.equals(value1, map[key1]);
    // Add enough entries to make sure the table grows.
    map[key2] = value2;
    Expect.equals(value2, map[key2]);
    Expect.equals(2, map.length);
    map[key3] = value3;
    Expect.equals(value2, map[key2]);
    Expect.equals(value3, map[key3]);
    map[key4] = value4;
    Expect.equals(value3, map[key3]);
    Expect.equals(value4, map[key4]);
    map[key5] = value5;
    Expect.equals(value4, map[key4]);
    Expect.equals(value5, map[key5]);
    map[key6] = value6;
    Expect.equals(value5, map[key5]);
    Expect.equals(value6, map[key6]);
    map[key7] = value7;
    Expect.equals(value6, map[key6]);
    Expect.equals(value7, map[key7]);
    map[key8] = value8;
    Expect.equals(value1, map[key1]);
    Expect.equals(value2, map[key2]);
    Expect.equals(value3, map[key3]);
    Expect.equals(value4, map[key4]);
    Expect.equals(value5, map[key5]);
    Expect.equals(value6, map[key6]);
    Expect.equals(value7, map[key7]);
    Expect.equals(value8, map[key8]);
    Expect.equals(8, map.length);

    map.remove(key4);
    Expect.equals(false, map.containsKey(key4));
    Expect.equals(7, map.length);

    // Test clearing the table.
    map.clear();
    Expect.equals(0, map.length);
    Expect.equals(false, map.containsKey(key1));
    Expect.equals(false, map.containsKey(key2));
    Expect.equals(false, map.containsKey(key3));
    Expect.equals(false, map.containsKey(key4));
    Expect.equals(false, map.containsKey(key5));
    Expect.equals(false, map.containsKey(key6));
    Expect.equals(false, map.containsKey(key7));
    Expect.equals(false, map.containsKey(key8));

    // Test adding and removing again.
    map[key1] = value1;
    Expect.equals(value1, map[key1]);
    Expect.equals(1, map.length);
    map[key2] = value2;
    Expect.equals(value2, map[key2]);
    Expect.equals(2, map.length);
    map[key3] = value3;
    Expect.equals(value3, map[key3]);
    map.remove(key3);
    Expect.equals(2, map.length);
    map[key4] = value4;
    Expect.equals(value4, map[key4]);
    map.remove(key4);
    Expect.equals(2, map.length);
    map[key5] = value5;
    Expect.equals(value5, map[key5]);
    map.remove(key5);
    Expect.equals(2, map.length);
    map[key6] = value6;
    Expect.equals(value6, map[key6]);
    map.remove(key6);
    Expect.equals(2, map.length);
    map[key7] = value7;
    Expect.equals(value7, map[key7]);
    map.remove(key7);
    Expect.equals(2, map.length);
    map[key8] = value8;
    Expect.equals(value8, map[key8]);
    map.remove(key8);
    Expect.equals(2, map.length);

    Expect.equals(true, map.containsKey(key1));
    Expect.equals(true, map.containsValue(value1));

    // Test Map.forEach.
    Map other_map = new Map();
    void testForEachMap(key, value) {
      other_map[key] = value;
    }

    map.forEach(testForEachMap);
    Expect.equals(true, other_map.containsKey(key1));
    Expect.equals(true, other_map.containsKey(key2));
    Expect.equals(true, other_map.containsValue(value1));
    Expect.equals(true, other_map.containsValue(value2));
    Expect.equals(2, other_map.length);

    other_map.clear();
    Expect.equals(0, other_map.length);

    // Test Collection.keys.
    void testForEachCollection(value) {
      other_map[value] = value;
    }

    Iterable keys = map.keys;
    keys.forEach(testForEachCollection);
    Expect.equals(true, other_map.containsKey(key1));
    Expect.equals(true, other_map.containsKey(key2));
    Expect.equals(true, other_map.containsValue(key1));
    Expect.equals(true, other_map.containsValue(key2));
    Expect.equals(true, !other_map.containsKey(value1));
    Expect.equals(true, !other_map.containsKey(value2));
    Expect.equals(true, !other_map.containsValue(value1));
    Expect.equals(true, !other_map.containsValue(value2));
    Expect.equals(2, other_map.length);
    other_map.clear();
    Expect.equals(0, other_map.length);

    // Test Collection.values.
    Iterable values = map.values;
    values.forEach(testForEachCollection);
    Expect.equals(true, !other_map.containsKey(key1));
    Expect.equals(true, !other_map.containsKey(key2));
    Expect.equals(true, !other_map.containsValue(key1));
    Expect.equals(true, !other_map.containsValue(key2));
    Expect.equals(true, other_map.containsKey(value1));
    Expect.equals(true, other_map.containsKey(value2));
    Expect.equals(true, other_map.containsValue(value1));
    Expect.equals(true, other_map.containsValue(value2));
    Expect.equals(2, other_map.length);
    other_map.clear();
    Expect.equals(0, other_map.length);

    // Test Map.putIfAbsent.
    map.clear();
    Expect.equals(false, map.containsKey(key1));
    map.putIfAbsent(key1, () => 10);
    Expect.equals(true, map.containsKey(key1));
    Expect.equals(10, map[key1]);
    Expect.equals(10, map.putIfAbsent(key1, () => 11));
  }

  static testKeys(Map map) {
    map[1] = 101;
    map[2] = 102;
    Iterable k = map.keys;
    Expect.equals(2, k.length);
    Iterable v = map.values;
    Expect.equals(2, v.length);
    Expect.equals(true, map.containsValue(101));
    Expect.equals(true, map.containsValue(102));
    Expect.equals(false, map.containsValue(103));
  }

  static testMain() {
    test(new Map());
    testKeys(new Map());
  }
}

main() {
  MapTest.testMain();
}
